Skip to content

chore(agents): harden worktree-first guard + surface Directive #11 via CLAUDE.md#2517

Merged
os-zhuang merged 1 commit into
mainfrom
fix/worktree-guard-hardening
Jul 2, 2026
Merged

chore(agents): harden worktree-first guard + surface Directive #11 via CLAUDE.md#2517
os-zhuang merged 1 commit into
mainfrom
fix/worktree-guard-hardening

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Why

Prime Directive #11 (worktree-first) is well written in AGENTS.md, yet agents (this one included) still edited on shared checkouts. Root cause wasn't the prose — it was enforcement + reach:

  1. The guard checked the wrong condition. guard-main-checkout.sh blocked only when branch == main. Creating a feature branch on the shared primary checkout passed the guard while the tree could still be switched/reset under you — the exact loophole that got hit (feat/studio-* on the shared objectui checkout; wip/session-off-main on framework).
  2. The guard only watched this repo. It inspected $CLAUDE_PROJECT_DIR, so editing a sibling repo (objectui/cloud) on its shared checkout from a framework session was silently unguarded.
  3. The directive never reached the agent's context. There's no CLAUDE.md (which is auto-loaded); AGENTS.md isn't. So the agent started blind to Migrate documentation site to Fumadocs with monorepo structure and shared content #11 and only learned it when the guard fired — where loophole Add metamodel interfaces for ObjectQL/ObjectUI contract #1 let it be bypassed.

What

  • Hook now enforces "in a linked worktree" (git rev-parse --git-dir under .git/worktrees/…), not branch != main. A branch on the shared checkout is blocked.
  • Hook now checks the edited file's own repo (parses tool_input.file_path from the PreToolUse stdin), so sibling repos are covered too — not just $CLAUDE_PROJECT_DIR.
  • New CLAUDE.md (auto-loaded): inlines the worktree-first rule + command, extends it to sibling repos, and points to AGENTS.md for the full playbook. (Inlining the critical rule beats a bare "go read AGENTS.md" — same weak indirection that failed.)
  • AGENTS.md Migrate documentation site to Fumadocs with monorepo structure and shared content #11 updated to match the hardened hook.

Verified (hook unit tests)

case expect result
file on framework primary (main) block ✅ exit 2
file in a framework worktree allow ✅ exit 0
file on objectui primary (main), from this session block ✅ exit 2 (cross-repo)
non-repo path allow ✅ exit 0
OS_ALLOW_MAIN_EDITS=1 allow ✅ exit 0

Authored from a worktree (framework-guardfix), per #11.

🤖 Generated with Claude Code

…a CLAUDE.md

The guard-main-checkout PreToolUse hook had two holes agents fell through:

1. It checked `branch != main`, so creating a feature branch on the SHARED
   primary checkout passed the guard while the tree could still be switched/reset
   under you. It now checks "is the edited file in a linked worktree" — a branch
   on the primary checkout is blocked. Enforces the directive's intent, not a proxy.

2. It only inspected $CLAUDE_PROJECT_DIR, so editing a sibling repo (objectui /
   cloud) on its shared checkout from this session was silently unguarded. It now
   parses the edited file's path and checks THAT repo's checkout — cross-repo safe.

Also:
- Add CLAUDE.md (auto-loaded into agent context, unlike AGENTS.md) that inlines the
  worktree-first rule + the command and points to AGENTS.md for the full playbook.
  The prior gap: AGENTS.md #11 was clear but never reached the agent's context.
- Update AGENTS.md #11 to describe the hardened hook behaviour.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 2, 2026 12:47pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation size/m labels Jul 2, 2026
@os-zhuang
os-zhuang merged commit d1fc9fa into main Jul 2, 2026
15 checks passed
@os-zhuang
os-zhuang deleted the fix/worktree-guard-hardening branch July 2, 2026 12:54
os-zhuang added a commit that referenced this pull request Jul 2, 2026
…fail-open) (#2519)

Follow-up to #2517. The guard ran `git -C "$(dirname file)"`, which fails when the
edited file's parent directory doesn't exist yet (a Write creating a new nested dir)
— and `|| exit 0` then let the edit through on the shared checkout. Now it walks up to
the nearest existing ancestor before resolving the repo, so new-file-in-new-dir writes
are guarded too. (Also applied to objectui#2160 / cloud#721.)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant